package com.flyan.game.motafx.core.util.script;

import cn.hutool.cache.Cache;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.crypto.digest.MD5;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import lombok.experimental.UtilityClass;

import java.lang.reflect.InvocationTargetException;

/**
 * Groovy 脚本工具类
 *
 * @author flyan
 * @version 1.0
 * @email flyan_by_chenu@sina.com
 * @since 2025/2/10
 */
@UtilityClass
public class GroovyScriptUtils {

    /**
     * 脚本缓存
     */
    private static final Cache<String, GroovyObject> SCRIPT_CACHE = new TimedCache<>(1000 * 60 * 60); // 1小时过期

    /**
     * 脚本加载器
     */
    private static final GroovyClassLoader GROOVY_CLASS_LOADER = new GroovyClassLoader();

    /**
     * 执行脚本
     *
     * @param script 脚本
     * @param method 方法
     * @param args 参数
     * @return 结果
     */
    public static Object invokeScript(String script, String method, Object... args) {
        var groovyObject = loadScript(script);
        if (groovyObject == null) {
            return null;
        }

        return groovyObject.invokeMethod(method, args);
    }

    /**
     * 加载脚本
     *
     * @param script 脚本
     * @return 脚本对象
     */
    private static GroovyObject loadScript(String script) {
        var key = getKey(script);
        GroovyObject groovyObject = null;
        try {
            groovyObject = SCRIPT_CACHE.get(key, () -> getGroovyObject(script));
        } catch (Exception e) {
            System.err.println("[GroovyScriptUtils] loadScript error: " + ExceptionUtil.getRootCauseMessage(e));
        }
        return groovyObject;
    }

    /**
     * 获取脚本对象
     *
     * @param script 脚本
     * @return 脚本对象
     */
    private GroovyObject getGroovyObject(String script) {
        GroovyObject groovyObject = null;
        try {
            Class<?> groovyClass = GROOVY_CLASS_LOADER.parseClass(script);
            groovyObject = (GroovyObject) groovyClass.getDeclaredConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            System.err.println("[GroovyScriptUtils] loadScript error: " + ExceptionUtil.getRootCauseMessage(e));
        }
        return groovyObject;
    }


    /**
     * 获取脚本对象 key
     *
     * @param script 脚本
     * @return key
     */
    private static String getKey(String script) {
        return MD5.create().digestHex16(script);
    }

}
